const express = require('express');
const app = express();
const fs = require("fs");
const readline = require('readline');


const ipCountryMap = {};

const filePath = "./ip.txt";
loadFile(filePath);


/**
 * 根据ip获取国家index，返回0表示ip地址库中未搜索到
 */
app.get('/country', function (req, res) {
    const remoteAddress = getRealIp(req);
    const countryCode = getCountryCode(remoteAddress);
    const rtn = {success: true, res: countryCode};
    res.end(JSON.stringify(rtn))
});

/**
 * 查询本机是否是中国范围ip
 */
app.get('/inChina', function (req, res) {
    const remoteAddress = getRealIp(req);
    const countryCode = getCountryCode(remoteAddress);
    const rtn = {success: true, res: countryCode === codeLib.CHN};
    res.end(JSON.stringify(rtn))
});

/**
 * 查询指定ip是否中国范围ip
 */
app.get('/inChina/:ip', function (req, res) {
    const remoteAddress = req.params.ip;
    const countryCode = getCountryCode(remoteAddress);
    const rtn = {success: true, res: countryCode === codeLib.CHN};
    res.end(JSON.stringify(rtn))
});

/**
 * 重新加载地址库
 */
app.put('/reload',function (req, res) {
    loadFile(filePath);
    res.end("server reload success.")
});


const server = app.listen(8080, '0.0.0.0', function () {

    const host = server.address().address;
    const port = server.address().port;

    console.log("应用实例，访问地址为 http://%s:%s", host, port)

});

/**
 * 获取用户真实ip，一般情况下，Nginx反向代理会将用户真实ip放在header中
 * @param req
 * @returns {*|string[]|string}
 */
function getRealIp(req) {
    return req.headers['x-forwarded-for'] ||
        req.connection.remoteAddress;
}

/**
 * 根据文件地址加载ip地址库
 * @param filePath
 */
function loadFile(filePath) {
    const fRead = fs.createReadStream(filePath);

    const objReadLine = readline.createInterface({
        input: fRead
    });
    objReadLine.on('line', function (line) {
        var obj = JSON.parse(line);
        ipCountryMap[obj.ip] = obj.country;
    });
}

/**
 * 根据ip获取国家代码
 * @param ip
 * @returns {number}
 */
function getCountryCode(ip) {
    let countryCode = ipCountryMap[cClassIpNum(ipToNumber(ip))];
    if (countryCode === undefined) {
        countryCode = 0
    }
    return countryCode
}


/**
 * IPv4地址分配是按C段来分，所以干掉后8位，保留前24位即可
 * @param ipNum
 * @returns {number}
 */
function cClassIpNum(ipNum) {
    return ipNum >>> 8
}

/**
 * ipv4地址字符串转数字
 * @param ip
 * @returns {number}
 */
function ipToNumber(ip) {
    const result = ip.split(".");
    if (!result) return -1;
    return (parseInt(result[0]) << 24
        | parseInt(result[1]) << 16
        | parseInt(result[2]) << 8
        | parseInt(result[3])) >>> 0;
}

/**
 * 数字转IPv4地址
 * @param INT
 * @returns {string}
 */
function numberToIp(INT) {
    if (INT < 0 || INT > 0xFFFFFFFF) {
        throw ("The number is not normal!");
    }
    return (INT >>> 24) + "." + (INT >> 16 & 0xFF) + "." + (INT >> 8 & 0xFF) + "." + (INT & 0xFF);
}

/**
 * 国家代码，参照维基百科2018年7月3日 (星期二) 06:08版国际奥委会国家编码列表
 * @type {{AFG: number, ALB: number, ALG: number, AND: number, ANG: number, ANT: number, ARG: number, ARM: number, ARU: number, ASA: number, AUS: number, AUT: number, AZE: number, BAH: number, BAN: number, BAR: number, BDI: number, BEL: number, BEN: number, BER: number, BHU: number, BIH: number, BIZ: number, BLR: number, BOL: number, BOT: number, BRA: number, BRN: number, BRU: number, BUL: number, BUR: number, CAF: number, CAM: number, CAN: number, CAY: number, CGO: number, CHA: number, CHI: number, CHN: number, CIV: number, CMR: number, COD: number, COK: number, COL: number, COM: number, CPV: number, CRC: number, CRO: number, CUB: number, CYP: number, CZE: number, DEN: number, DJI: number, DMA: number, DOM: number, ECU: number, EGY: number, ERI: number, ESA: number, ESP: number, EST: number, ETH: number, FIJ: number, FIN: number, FRA: number, FSM: number, GAB: number, GAM: number, GBR: number, GBS: number, GEO: number, GEQ: number, GER: number, GHA: number, GRE: number, GRN: number, GUA: number, GUI: number, GUM: number, GUY: number, HAI: number, HKG: number, HON: number, HUN: number, INA: number, IND: number, IRI: number, IRL: number, IRQ: number, ISL: number, ISR: number, ISV: number, ITA: number, IVB: number, JAM: number, JOR: number, JPN: number, KAZ: number, KEN: number, KGZ: number, KIR: number, KOR: number, KOS: number, KSA: number, KUW: number, LAO: number, LAT: number, LBA: number, LBN: number, LBR: number, LCA: number, LES: number, LIE: number, LTU: number, LUX: number, MAD: number, MAR: number, MAS: number, MAW: number, MDA: number, MDV: number, MEX: number, MGL: number, MHL: number, MKD: number, MLI: number, MLT: number, MNE: number, MON: number, MOZ: number, MRI: number, MTN: number, MYA: number, NAM: number, NCA: number, NED: number, NEP: number, NGR: number, NIG: number, NOR: number, NRU: number, NZL: number, OMA: number, PAK: number, PAN: number, PAR: number, PER: number, PHI: number, PLE: number, PLW: number, PNG: number, POL: number, POR: number, PRK: number, PUR: number, QAT: number, ROU: number, RSA: number, RUS: number, RWA: number, SAM: number, SEN: number, SEY: number, SGP: number, SKN: number, SLE: number, SLO: number, SMR: number, SOL: number, SOM: number, SRB: number, SRI: number, SSD: number, STP: number, SUD: number, SUI: number, SUR: number, SVK: number, SWE: number, SWZ: number, SYR: number, TAN: number, TGA: number, THA: number, TJK: number, TKM: number, TLS: number, TOG: number, TPE: number, TTO: number, TUN: number, TUR: number, TUV: number, UAE: number, UGA: number, UKR: number, URU: number, USA: number, UZB: number, VAN: number, VEN: number, VIE: number, VIN: number, YEM: number, ZAM: number, ZIM: number}}
 */
const codeLib = {
    "AFG":1,	 //阿富汗
    "ALB":2,	 //阿尔巴尼亚
    "ALG":3,	 //阿尔及利亚	AGR（1964），AGL（1968夏）
    "AND":4,	 //安道尔
    "ANG":5,	 //安哥拉
    "ANT":6,	 //安提瓜和巴布达
    "ARG":7,	 //阿根廷
    "ARM":8,	 //亚美尼亚
    "ARU":9,	 //阿鲁巴
    "ASA":10,	 //美属萨摩亚
    "AUS":11,	 //澳大利亚
    "AUT":12,	 //奥地利
    "AZE":13,	 //阿塞拜疆
    "BAH":14,	 //巴哈马
    "BAN":15,	 //孟加拉国
    "BAR":16,	 //巴巴多斯	BAD（1964）
    "BDI":17,	 //布隆迪
    "BEL":18,	 //比利时
    "BEN":19,	 //贝宁	DAY（1964），DAH（1968–1976）
    "BER":20,	 //百慕大
    "BHU":21,	 //不丹
    "BIH":22,	 //波斯尼亚和黑塞哥维那	BSH（1992夏）
    "BIZ":23,	 //伯利兹	HBR（1968–1972）
    "BLR":24,	 //白俄罗斯
    "BOL":25,	 //玻利维亚
    "BOT":26,	 //博茨瓦纳
    "BRA":27,	 //巴西
    "BRN":28,	 //巴林
    "BRU":29,	 //文莱
    "BUL":30,	 //保加利亚
    "BUR":31,	 //布基纳法索	VOL（1972–1984）
    "CAF":32,	 //中非共和国	AFC（1968）
    "CAM":33,	 //柬埔寨	CAB（1964），KHM（1972–1976）
    "CAN":34,	 //加拿大
    "CAY":35,	 //开曼群岛
    "CGO":36,	 //刚果共和国
    "CHA":37,	 //查德	CHD（1964）
    "CHI":38,	 //智利	CIL（1956冬， 1960夏）
    "CHN":39,	 //中国	PRC（1952夏）
    "CIV":40,	 //科特迪瓦	IVC（1964），CML（1968）
    "CMR":41,	 //喀麦隆
    "COD":42,	 //刚果民主共和国	COK（1968），ZAI（1972–1996）
    "COK":43,	 //库克群岛
    "COL":44,	 //哥伦比亚
    "COM":45,	 //科摩罗
    "CPV":46,	 //佛得角
    "CRC":47,	 //哥斯达黎加	COS（1964）
    "CRO":48,	 //克罗地亚
    "CUB":49,	 //古巴
    "CYP":50,	 //塞浦路斯
    "CZE":51,	 //捷克	TCH（1984）
    "DEN":52,	 //丹麦	DAN（1960夏， 1968冬），DIN（1968夏）
    "DJI":53,	 //吉布提
    "DMA":54,	 //多米尼克
    "DOM":55,	 //多米尼加
    "ECU":56,	 //厄瓜多尔
    "EGY":57,	 //埃及	RAU（1960， 1968），UAR（1964）
    "ERI":58,	 //厄立特里亚
    "ESA":59,	 //萨尔瓦多	SAL（1964–1976）
    "ESP":60,	 //西班牙	SPA（1956–1964， 1968冬）
    "EST":61,	 //爱沙尼亚
    "ETH":62,	 //埃塞俄比亚	ETI（1960， 1968）
    "FIJ":63,	 //斐济	FIG（1960）
    "FIN":64,	 //芬兰
    "FRA":65,	 //法国
    "FSM":66,	 //密克罗尼西亚
    "GAB":67,	 //加蓬
    "GAM":68,	 //冈比亚
    "GBR":69,	 //英国	GRB（1956冬–1960），GBI（1964）
    "GBS":70,	 //几内亚比绍
    "GEO":71,	 //格鲁吉亚
    "GEQ":72,	 //赤道几内亚
    "GER":73,	 //德国	ALL（1968冬），ALE（1968夏）
    "GHA":74,	 //加纳
    "GRE":75,	 //希腊
    "GRN":76,	 //格林纳达
    "GUA":77,	 //危地马拉	GUT（1964）
    "GUI":78,	 //几内亚
    "GUM":79,	 //关岛
    "GUY":80,	 //圭亚那	GUA（1960），GUI（1964）
    "HAI":81,	 //海地
    "HKG":82,	 //中国香港	HOK（1960–1968）
    "HON":83,	 //洪都拉斯
    "HUN":84,	 //匈牙利	UNG（1956冬， 1960夏）
    "INA":85,	 //印尼	INS（1960）
    "IND":86,	 //印度
    "IRI":87,	 //伊朗	IRN（1956–1988），IRA（1968冬）
    "IRL":88,	 //爱尔兰
    "IRQ":89,	 //伊拉克	IRK（1960， 1968）
    "ISL":90,	 //冰岛	ICE（1960冬， 1964夏）
    "ISR":91,	 //以色列
    "ISV":92,	 //维尔京群岛
    "ITA":93,	 //意大利
    "IVB":94,	 //英属维尔京群岛
    "JAM":95,	 //牙买加
    "JOR":96,	 //约旦
    "JPN":97,	 //日本	GIA（1956冬， 1960夏），JAP（1960冬）
    "KAZ":98,	 //哈萨克
    "KEN":99,	 //肯尼亚
    "KGZ":100,	 //吉尔吉斯
    "KIR":101,	 //基里巴斯
    "KOR":102,	 //韩国	COR（1956冬， 1960夏， 1968夏， 1972夏）
    "KOS":103,	 //科索沃
    "KSA":104,	 //沙特阿拉伯	ARS（1968–1976），SAU（1980–1984）
    "KUW":105,	 //科威特
    "LAO":106,	 //老挝
    "LAT":107,	 //拉脱维亚
    "LBA":108,	 //利比亚	LYA（1964），LBY（1968冬）
    "LBN":109,	 //黎巴嫩	LEB（1960冬， 1964夏），LIB（1964-2016）
    "LBR":110,	 //利比里亚
    "LCA":111,	 //圣卢西亚
    "LES":112,	 //莱索托
    "LIE":113,	 //列支敦士登	LIC（1956冬， 1964夏， 1968冬）
    "LTU":114,	 //立陶宛	LIT（1992冬）
    "LUX":115,	 //卢森堡
    "MAD":116,	 //马达加斯加	MAG（1964）
    "MAR":117,	 //摩洛哥	MRC（1964）
    "MAS":118,	 //马来西亚	MAL（1964–1988）
    "MAW":119,	 //马拉维
    "MDA":120,	 //摩尔多瓦	MLD（1994）
    "MDV":121,	 //马尔代夫
    "MEX":122,	 //墨西哥
    "MGL":123,	 //蒙古	MON（1968冬）
    "MHL":124,	 //马绍尔群岛
    "MKD":125,	 //马其顿
    "MLI":126,	 //马里
    "MLT":127,	 //马耳他	MAT（1960–1964）
    "MNE":128,	 //黑山
    "MON":129,	 //摩纳哥
    "MOZ":130,	 //莫桑比克
    "MRI":131,	 //毛里求斯
    "MTN":132,	 //毛里塔尼亚
    "MYA":133,	 //缅甸	BIR（1960， 1968–1988），BUR（1964）
    "NAM":134,	 //纳米比亚
    "NCA":135,	 //尼加拉瓜	NCG（1964），NIC（1968）
    "NED":136,	 //荷兰	OLA（1956冬），NET（1960冬），PBA（1960夏），NLD（1964夏），HOL（1968–1988）
    "NEP":137,	 //尼泊尔
    "NGR":138,	 //尼日利亚	NIG（1960夏），NGA（1964）
    "NIG":139,	 //尼日尔	NGR（1964）
    "NOR":140,	 //挪威
    "NRU":141,	 //瑙鲁
    "NZL":142,	 //新西兰	NZE（1960， 1968冬）
    "OMA":143,	 //阿曼
    "PAK":144,	 //巴基斯坦
    "PAN":145,	 //巴拿马
    "PAR":146,	 //巴拉圭
    "PER":147,	 //秘鲁
    "PHI":148,	 //菲律宾	FIL（1960， 1968）
    "PLE":149,	 //巴勒斯坦
    "PLW":150,	 //帕劳
    "PNG":151,	 //巴布亚新几内亚	NGY（1976–1980），NGU（1984–1988）
    "POL":152,	 //波兰
    "POR":153,	 //葡萄牙
    "PRK":154,	 //朝鲜	NKO（1964夏， 1968冬），CDN（1968）
    "PUR":155,	 //波多黎各	PRI（1960），PRO（1968）
    "QAT":156,	 //卡塔尔
    "ROU":157,	 //罗马尼亚	ROM（1956–1960， 1972–2006），RUM（1964–1968）
    "RSA":158,	 //南非	SAF（1960–1972）
    "RUS":159,	 //俄罗斯	OAR（2018冬）
    "RWA":160,	 //卢旺达
    "SAM":161,	 //萨摩亚
    "SEN":162,	 //塞内加尔	SGL（1964）
    "SEY":163,	 //塞舌尔
    "SGP":164,	 //新加坡	SIN（1959–2016）
    "SKN":165,	 //圣基茨和尼维斯
    "SLE":166,	 //塞拉利昂	SLA（1968）
    "SLO":167,	 //斯洛文尼亚
    "SMR":168,	 //圣马力诺	SMA（1960–1964）
    "SOL":169,	 //所罗门群岛
    "SOM":170,	 //索马里
    "SRB":171,	 //塞尔维亚
    "SRI":172,	 //斯里兰卡	CEY（1960-1964， 1972），CEI（1968夏）
    "SSD":173,	 //南苏丹
    "STP":174,	 //圣多美和普林西比
    "SUD":175,	 //苏丹
    "SUI":176,	 //瑞士	SVI（1956冬， 1960夏），SWI（1960冬， 1964夏）
    "SUR":177,	 //苏里南
    "SVK":178,	 //斯洛伐克
    "SWE":179,	 //瑞典	SVE（1956冬， 1960夏），SUE（1968夏）
    "SWZ":180,	 //斯威士兰
    "SYR":181,	 //叙利亚	RAU（1960），SIR（1968）
    "TAN":182,	 //坦桑尼亚
    "TGA":183,	 //汤加	TON（1984）
    "THA":184,	 //泰国
    "TJK":185,	 //塔吉克
    "TKM":186,	 //土库曼斯坦
    "TLS":187,	 //东帝汶	IOA（2000）
    "TOG":188,	 //多哥
    "TPE":189,	 //中华台北	RCF（1960），TWN（1964–1968），ROC（1972–1976）
    "TTO":190,	 //特立尼达和多巴哥	TRT（1964–1968），TRI（1972–2012）
    "TUN":191,	 //突尼斯
    "TUR":192,	 //土耳其
    "TUV":193,	 //图瓦卢
    "UAE":194,	 //阿拉伯联合酋长国
    "UGA":195,	 //乌干达
    "UKR":196,	 //乌克兰
    "URU":197,	 //乌拉圭	URG（1968）
    "USA":198,	 //美国	SUA（1960夏），EUA（1968夏）
    "UZB":199,	 //乌兹别克
    "VAN":200,	 //瓦努阿图
    "VEN":201,	 //委内瑞拉
    "VIE":202,	 //越南	VET（1964），VNM（1968–1976）
    "VIN":203,	 //圣文森特和格林纳丁斯
    "YEM":204,	 //也门
    "ZAM":205,	 //赞比亚	NRH（1964）
    "ZIM":206	 //津巴布韦
};
